package is.ru.server;

/**
 * Created in IntelliJ IDEA.
 * Students: Jón Geir Sigurbjörnsson, Kristinn Helgi Hilmarsson, Jón Rúnar Arnarsson
 * Class: T-408-STNE, Stýrikerfi og netkerfi, 2011-1
 * Project: Programming assignment 3: HTTP web server
 * Date: 16.3.2011
 * Time: 20:17
 */

import java.io.*;
import java.net.*;

public class HttpRuClient
{
    static final byte[] EOL = {(byte) '\r', (byte) '\n'};

    public static void main(String[] args)
    {
        HttpRuClient client = new HttpRuClient();
        client.start(args);
    }

    public void start(String[] args)
    {
        // Basic info is hardcoded so if the user forgot to put some args the program will run with the given settings
        String protocol = "tcp";
        String address = "";
        int port = 1234;

        // Info worked from args
        if (args.length == 1)
        {
            protocol = args[0];
        }

        else if (args.length == 2)
        {
            protocol = args[0];
            port = Integer.parseInt(args[1]);
        }
        else if (args.length == 3)
        {
            protocol = args[0];
            port = Integer.parseInt(args[1]);
            address = args[2];
        }
        // Print out the info the user that the user is trying to connect to
        System.out.format("Start client! Protocol: %s, Port: %s, IP Address: %s \n\r", protocol, port, address);
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        try
        {
            try
            {
                while (true)
                {
                    System.out.println("Enter URI: ");
                    String uri = reader.readLine();

                    //The connection will be disconnected if the user enter exit
                    if (uri.equalsIgnoreCase("exit"))
                        break;

                    // Here we format the request that user entered
                    String request = formatRequest(uri);

                    if (protocol.equalsIgnoreCase("tcp"))
                    {
                        tcp(request, address, port);
                    }
                    else if (protocol.equalsIgnoreCase("udp"))
                    {
                        udp(request, address, port);
                    }
                }
            } finally
            {
                if (reader != null)
                    reader.close();
            }
        } catch (IOException e)
        {
            System.out.println("HttpRuClient IOException");
            e.printStackTrace();
        }

        System.out.println("Stop client!");
    }

    // Format the request
    private static String formatRequest(String uri)
    {
        StringBuffer sb = new StringBuffer();
        sb.append("GET ").append(uri).append(" HTTP/1.1").append(EOL);
        return sb.toString();
    }


    // This function will be used if the protocol was tcp
    public void tcp(String request, String address, int port)
    {
        DataOutputStream os = null;
        DataInputStream is = null;
        Socket clientSocket = null;

        try
        {
            try
            {
                // Socket and InputStream and OutputStream created
                clientSocket = new Socket(address, port);
                os = new DataOutputStream(clientSocket.getOutputStream());
                is = new DataInputStream(clientSocket.getInputStream());

                os.write(request.getBytes());
                os.write( EOL );
                os.flush();

                BufferedReader bin = new BufferedReader(new InputStreamReader(is));
                String line;
                while ((line = bin.readLine()) != null)
                {
                    System.out.println(line);
                }

            } finally // Close all the streams that where open
            {
                if (os != null)
                    os.close();
                if (is != null)
                    is.close();
                if (clientSocket != null)
                    clientSocket.close();
            }

        } catch (UnknownHostException e)  //  error handling if the server host  was not found
        {
            System.err.println("Don't know about host: " + address + " with port: " + port);
        } catch (IOException e)    // error handling if there was I/O connection problem
        {
            System.err.println("Couldn't get I/O for the connection to the host:" + address);
        }
    }
    // This function will be used if the protocol was dcp
    public void udp(String request, String address, int port)
    {
        byte[] sendData;
        byte[] receiveData = new byte[2048];
        DatagramSocket clientSocket = null;
        try
        {
            try
            {
                // Create new datagramSocet
                clientSocket = new DatagramSocket();
                InetAddress IPAddress = InetAddress.getByName(address);
                // get the request in bytes
                sendData = request.getBytes();
                // Create new datagramPacket with the given info
                DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port);
                // Send the packet
                clientSocket.send(sendPacket);
                // Create new datagramPacket who will receive data from server
                DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                // Receive the Packet from the server
                clientSocket.receive(receivePacket);

                String response = new String(receivePacket.getData());
                System.out.println(response.replaceAll("\\u0000+$", ""));

            } finally
            {
                if (clientSocket != null)
                    clientSocket.close();
            }

        } catch (IOException e)
        {
            System.out.println("HttpRuClient IOException");
            e.printStackTrace();
        }
    }
}

